#ifndef __POLLER_H__
#define __POLLER_H__
#include <list>
#include <arpa/inet.h>
#include <sys/poll.h>
#include "myepoll.h"
#include <list>

#define EPOLL_DATA_SLOT(x)	((x)->data.u64 & 0xFFFFFFFF)
#define EPOLL_DATA_SEQ(x)	((x)->data.u64 >> 32)

using namespace std;

class CPollerUnit;
class CPollerObject;

struct CEpollSlot {
	uint32_t seq;
	CPollerObject *poller;
	struct CEpollSlot *freeList;
};

class CPollerObject {
friend class CPollerUnit;
public:
	CPollerObject (CPollerUnit *thread=NULL, int fd=0);
	virtual ~CPollerObject ();

	virtual void InputNotify (void);
	virtual void OutputNotify (void);
	virtual void HangupNotify (void);
	virtual bool OnTimer(time_t t);

	void EnableInput(void) {
		newEvents |= EPOLLIN;
	}
	void EnableOutput(void) {
		newEvents |= EPOLLOUT;
	}
	void DisableInput(void) {
		newEvents &= ~EPOLLIN;
	}
	void DisableOutput(void) {
		newEvents &= ~EPOLLOUT;
	}

	void EnableInput(bool i) {
		if(i)
			newEvents |= EPOLLIN;
		else
			newEvents &= ~EPOLLIN;
	}
	void EnableOutput(bool o) {
		if(o)
			newEvents |= EPOLLOUT;
		else
			newEvents &= ~EPOLLOUT;
	}

	void SetTimeOut(int dt)
	{
		timeout = dt;
	}

	int GetTimeOut()
	{
		return timeout;
	}

	void Active()
	{
		activetime = time(NULL);
	}

	int AttachPoller (CPollerUnit *thread=NULL);
	int AttachTimer();
	int DetachTimer();
	
	
	int DetachPoller (void);
	int ApplyEvents ();

	void InitPollFd(struct pollfd *);

protected:
	int netfd;
	CPollerUnit *ownerUnit;
	int newEvents;
	int oldEvents;
	struct CEpollSlot *epslot;
	time_t activetime;
	int timeout;
	int flag;
	list<CPollerObject *>::iterator iter;
};

class CPollerUnit {
public:
	friend class CPollerObject;
	CPollerUnit(int mp);
	virtual ~CPollerUnit();

	int SetMaxPollers(int mp);
	int GetMaxPollers(void) const { return maxPollers; }
	int InitializePollerUnit(void);
	void WaitPollerEvents(int);
	void ProcessPollerEvents(void);
	int GetFD(void) { return epfd; }

	void CloseAll();
	
	list<CPollerObject *>::iterator EnableTimeOut(CPollerObject *o)
	{
		 timerlist.push_back(o);
		 return --timerlist.end();
	}

	//virtual void FreeProcess(void);	
	
protected:
	void OnTimer(void);
private:
	int VerifyEvents(struct epoll_event *);
	int Epctl (int op, int fd, struct epoll_event *events);
	int GetSlotId (CEpollSlot *p) {return ((char*)p - (char*)pollerTable) / sizeof (CEpollSlot);}


	void FreeEpollSlot (CEpollSlot *p);
	struct CEpollSlot *AllocEpollSlot ();

	struct epoll_event *ep_events;
	int epfd;
	int maxPollers;
	int usedPollers;
	struct CEpollSlot *freeSlotList;	
	struct CEpollSlot *pollerTable;

	int nrEvents;

	list<CPollerObject *> timerlist;
	list<CPollerObject *>::iterator iter;

};

#endif
